package sudoku;

import java.util.ArrayList;

import evo.Evolution;
import evo.IInstance;

public class Run {

	
	public static void main(String[] args)
	{
		int generations = 10000;
		int population = 50;
		
		int[] board = new int[SudokuProblem.SIZE*SudokuProblem.SIZE];
		int[] indices = new int[] {1,4,8,11,16,20,22,23,24,25,27,29,32,38,42,48,51,53,55,56,57,58,60,64,69,72,76,79};
		int[] vals = new int[] {2,6,8,1,4,7,8,5,6,2,7,3,4,8,5,6,4,1,3,6,5,7,9,9,7,1,4,5};
		
		assert indices.length == vals.length;
		
		for (int i = 0; i < indices.length; i++) {
			board[indices[i]] = vals[i];
		}
		
		SudokuProblem prob = new SudokuProblem(board);
		
		SudokuSolution tmp = new SudokuSolution(prob);
		printSolution(tmp);
		
		SudokuBuilder builder = new SudokuBuilder(prob);
		
		double pmutate = 0.1;
		double clonePart = 0.3;
		
		Evolution evo = new Evolution(builder, population, pmutate, clonePart);

		for (int i = 0; i < generations; i++) {
			if (i%50==0)
				System.out.println("generation "+i+" best fitness: "+getBestFitness(evo.getCurrentGen()));
			evo.advanceGen();
		}
		ArrayList<IInstance> gen = evo.getCurrentGen();
		SudokuSolution sol = (SudokuSolution)gen.get(getBestFitnessIndex(gen));
		printSolution(sol);
	}
	
	
	private static int getBestFitnessIndex(ArrayList<IInstance> gen)
	{
		int besti = 0;
		for (int i = 0; i < gen.size(); i++) {
			if (gen.get(i).getFitness() > gen.get(besti).getFitness())
			{
				besti = i;
			}
		}
		return besti;
	}
	
	private static double getBestFitness(ArrayList<IInstance> gen)
	{
		int besti = 0;
		for (int i = 0; i < gen.size(); i++) {
			if (gen.get(i).getFitness() > gen.get(besti).getFitness())
			{
				besti = i;
			}
		}
		return gen.get(besti).getFitness();
	}
	
	
	
	private static void printSolution(SudokuSolution sol)
	{
		int r = (int)Math.sqrt(SudokuProblem.SIZE);
		for (int i = 0; i < SudokuProblem.SIZE; i++) {
			for (int j = 0; j < SudokuProblem.SIZE; j++) {
				
				if (j%r==0)
					System.out.print("|");
				System.out.print(String.format("%4d", sol.board[i*SudokuProblem.SIZE+j]));
			}
			System.out.println("|");
			System.out.println("------------------------------------------");
		}
	}
	
}
